<template>
  <div class="upload-list">
    <div class="operate-btns">
      <el-input
        v-model="search.name"
        v-haspermi="['bxy:file:search']"
        :placeholder="$t('filePond.enterFileName')"
        style="width:200px;margin-right:15px;"
        clearable
      />
      <el-button v-haspermi="['bxy:file:search']" type="primary" icon="el-icon-search" @click="searchList">{{
        $t('common.search')
      }}</el-button>
      <el-button
        v-haspermi="['bxy:file:upload']"
        type="success"
        icon="el-icon-document-copy"
        @click="uploadFile(true)"
      >{{ $t('filePond.fileUpload') }}</el-button>
      <el-button
        v-haspermi="['bxy:file:copy']"
        type="primary"
        :disabled="isDisabled"
        fuzhi
        class="delete"
        icon="el-icon-document-checked"
        @click="copyFileUrlZip"
      >
        {{ $t('filePond.copyDownloadLink') }}
      </el-button>
      <el-button
        ref="zipUrl"
        v-clipboard:copy="zipUrl"
        v-clipboard:success="onCopyFiles"
        style="position:absolute;visibility: hidden;"
        size="mini"
        type="primary"
        plain
      >{{ $t('filePond.copyDownloadLink') }}</el-button>
      <el-button
        v-haspermi="['bxy:file:delete']"
        type="danger"
        :disabled="isDisabled"
        class="delete"
        icon="el-icon-delete"
        @click="deleteFiles"
      >
        {{ $t('filePond.bulkDelete') }}
        <span v-show="deleteNums">({{ deleteNums }})</span>
      </el-button>
    </div>
    <el-table
      ref="multipleTable"
      :data="fileList"
      style="width: 100%"
      stripe
      border
      :default-sort="{ prop: 'create_time', order: 'descending' }"
      :row-key="getRowKeys"
      @selection-change="handleSelectionChange"
      @sort-change="handleSortChange"
    >
      <el-table-column
        type="selection"
        width="55"
        :reserve-selection="true"
        align="center"
      />
      <el-table-column type="index" :label="$t('common.num')" width="50" />
      <el-table-column prop="name" :label="$t('filePond.fileName')" />
      <el-table-column prop="size" :label="$t('filePond.fileSize')" sortable>
        <template slot-scope="scope">
          {{ unitToExpect(scope.row.size) }}
        </template>
      </el-table-column>
      <el-table-column
        prop="create_time"
        :label="$t('filePond.createTime')"
        sortable
      >
        <template slot-scope="scope">
          {{ formatDate(scope.row.create_time) }}
        </template>
      </el-table-column>

      <el-table-column prop="" :label="$t('filePond.expiryTime')">
        <template slot-scope="scope">
          {{ formatDate(scope.row.expire_time) }}
        </template>
      </el-table-column>
      <el-table-column :label="$t('common.operate')" width="320">
        <template slot-scope="scope">
          <el-button
            v-haspermi="['bxy:file:download']"
            size="mini"
            type="primary"
            plain
            @click="downloadFile(scope.row)"
          >{{ $t('common.download') }}
          </el-button>
          <el-button
            v-clipboard:copy="scope.row.path"
            v-clipboard:success="onCopy"
            v-haspermi="['bxy:file:copy']"
            size="mini"
            type="primary"
            plain
          >{{ $t('filePond.copyDownloadLink') }}</el-button>
          <el-button
            v-haspermi="['bxy:file:delete']"
            size="mini"
            type="danger"
            plain
            @click="deleteFile(scope.row)"
          >{{ $t('common.delete') }}</el-button>
        </template>
      </el-table-column>
    </el-table>
    <div class="pager">
      <el-pagination
        :current-page="search.page"
        :page-sizes="[10, 50, 100, 400]"
        :page-size="search.size"
        layout="total, sizes, prev, pager, next, jumper"
        :total="totals"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
    <el-dialog
      :title="$t('filePond.fileUpload')"
      :visible.sync="dialogVisible"
      width="500px"
      :before-close="handleClose"
      :close-on-click-modal="false"
    >
      <div class="file-list">
        <file-pond
          ref="pond"
          :label-idle="$t('filePond.labelIdle')"
          :label-invalid-field="$t('filePond.labelInvalidField')"
          :label-file-waiting-for-size="$t('filePond.labelFileWaitingForSize')"
          :label-file-size-not-available="
            $t('filePond.labelFileSizeNotAvailable')
          "
          :label-file-loading="$t('filePond.labelFileLoading')"
          :label-file-load-error="$t('filePond.labelFileLoadError')"
          :label-file-processing="$t('filePond.labelFileProcessing')"
          :label-file-processing-complete="
            $t('filePond.labelFileProcessingComplete')
          "
          :label-file-processing-aborted="
            $t('filePond.labelFileProcessingAborted')
          "
          :label-file-processing-error="errorMsg"

          :label-file-processing-revert-error="
            $t('filePond.labelFileProcessingRevertError')
          "
          :label-file-remove-error="$t('filePond.labelFileRemoveError')"
          :label-tap-to-cancel="$t('filePond.labelTapToCancel')"
          :label-tap-to-retry="$t('filePond.labelTapToRetry')"
          :label-tap-to-undo="$t('filePond.labelTapToUndo')"
          :label-button-remove-item="$t('filePond.labelButtonRemoveItem')"
          :label-button-abort-item-load="
            $t('filePond.labelButtonAbortItemLoad')
          "
          :label-button-retry-item-load="
            $t('filePond.labelButtonRetryItemLoad')
          "
          :label-button-abort-item-processing="
            $t('filePond.labelButtonAbortItemProcessing')
          "
          :label-button-undo-item-processing="
            $t('filePond.labelButtonUndoItemProcessing')
          "
          :label-button-retry-item-processing="
            $t('filePond.labelButtonRetryItemProcessing')
          "
          :label-button-process-item="$t('filePond.labelButtonProcessItem')"
          :label-max-file-size-exceeded="
            $t('filePond.labelMaxFileSizeExceeded')
          "
          :label-max-file-size="$t('filePond.labelMaxFileSize')"
          :label-max-total-file-size-exceeded="
            $t('filePond.labelMaxTotalFileSizeExceeded')
          "
          :label-max-total-file-size="$t('filePond.labelMaxTotalFileSize')"
          :label-file-type-not-allowed="$t('filePond.labelFileTypeNotAllowed')"
          :file-validate-type-label-expected-types="
            $t('filePond.fileValidateTypeLabelExpectedTypes')
          "
          :image-validate-size-label-format-error="
            $t('filePond.imageValidateSizeLabelFormatError')
          "
          :image-validate-size-label-image-size-too-small="
            $t('filePond.imageValidateSizeLabelImageSizeTooSmall')
          "
          :image-validate-size-label-image-size-too-big="
            $t('filePond.imageValidateSizeLabelImageSizeTooBig')
          "
          :image-validate-size-label-expected-min-size="
            $t('filePond.imageValidateSizeLabelExpectedMinSize')
          "
          :image-validate-size-label-expected-max-size="
            $t('filePond.imageValidateSizeLabelExpectedMaxSize')
          "
          :image-validate-size-label-image-resolution-too-low="
            $t('filePond.imageValidateSizeLabelImageResolutionTooLow')
          "
          :image-validate-size-label-image-resolution-too-high="
            $t('filePond.imageValidateSizeLabelImageResolutionTooHigh')
          "
          :image-validate-size-label-expected-min-resolution="
            $t('filePond.imageValidateSizeLabelExpectedMinResolution')
          "
          :image-validate-size-label-expected-max-resolution="
            $t('filePond.imageValidateSizeLabelExpectedMaxResolution')
          "
          name="file"
          :chunk-force="false"
          :chunk-uploads="true"
          :chunk-size="1024 * 1024 * 200"
          :allow-multiple="uploadType"
          :server="{
            url: `${url}${uploadApi}`,
            methods: 'POST',
            headers: {
              Authorization: getToken() // 上传接口的认证处理，因为没有走全局拦截函数
            },
            patch:{
              onerror:(res)=>{
                return res
              },
            },
            process:{
              onerror:(res)=>{
                return res
              },
            }
          }"
          :files="uploadFiles"
          :instant-upload="instantUpload"
          @init="handleFilePondInit"
        />
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button type="warning" @click="sureUploadFile()">
          <span>{{ $t('filePond.sureUpload') }}</span>
        </el-button>
        <el-button
          @click="
            dialogVisible = false;
            uploadFiles = [];
          "
        >{{ $t('filePond.close') }}</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { getToken } from '@/utils/auth';
import { formatDate, unitToExpect } from '@/utils/index';
import { getList, deleteFile, copyFileUrl } from '@/api/upload';
import { mapGetters } from 'vuex';
import vueFilePond from 'vue-filepond';
import 'filepond/dist/filepond.min.css';
const FilePond = vueFilePond();
export default {
  name: 'Upload',
  components: {
    FilePond,
  },
  data() {
    return {
      url: `${window.origin}`,
      uploadApi: '/app-template/api/files/single-upload',
      totals: 0,
      zipUrl: null,
      filesId: null,
      fileLen: null,
      code: undefined,
      username: undefined,
      tabPosition: 'left',
      uploadFiles: [],
      uploadType: false,
      txt: '',
      fileList: [],
      search: {
        name: '',
        page: 1,
        size: 10,
        sort: 'create_time,desc',
      },
      currentPage: 4,
      dialogVisible: false,
      instantUpload: false,
      goLogin: false,
      isDisabled: true,
      multipleSelection: [],
      deleteNums: null,
      selectNoticesIds: [],
    };
  },
  computed: {
    ...mapGetters(['name']),
  },
  created() {
    this.init();
  },
  methods: {
    /**
     * 页面初始化方法
     */
    init() {
      this.getList();
    },
    /**
     * 获取文件列表
     */
    async getList() {
      const res = await getList(this.search);
      this.fileList = res.data;
      this.totals = Number(res.headers['x-total-count']);
    },
    /**
     * 按名称搜索
     */
    searchList() {
      this.getList();
    },
    /**
     * 根据表格的排序条件发生变化触发请求
     * @param {Object} row 表格栏目对象（包含每条栏目的数据和属性）
     */
    handleSortChange(row) {
      this.search.page = 1;
      const sortName = row.prop;
      const sortType = row.order === 'descending' ? 'desc' : 'asc';
      this.search.sort = sortName + ',' + sortType;
      this.getList();
    },
    /**
     * 删除单文件接口处理
     * @param {Object} row 删除文件详细数据
     */
    deleteFile(row) {
      if (this.isExpire(row.updateTime)) {
        return;
      }
      this.$confirm(this.$t('filePond.deleteFileTip'), this.$t('common.tips'), {
        confirmButtonText: this.$t('common.sure'),
        cancelButtonText: this.$t('common.cancel'),
        type: 'warning',
      }).then(() => {
        deleteFile(row.id).then(() => {
          this.$message.success(this.$t('filePond.deleteFileSuccess'));
          this.getList();
        });
      });
    },
    /**
     * 批量删除文件
     */
    deleteFiles() {
      this.$confirm(
        this.$t('filePond.deleteFilesTip'),
        this.$t('common.tips'),
        {
          confirmButtonText: this.$t('common.sure'),
          cancelButtonText: this.$t('common.cancel'),
          type: 'warning',
        }
      ).then(() => {
        this.multipleDelete();
      });
    },
    /**
     * 批量删除接口
     */
    multipleDelete() {
      const ids = this.selectNoticesIds.toString();
      deleteFile(ids).then(() => {
        this.$message.success(this.$t('filePond.deleteFilesSuccess'));
        this.getList();
        this.clearMultipleSelect();
      });
    },
    /**
     * 下载单文件处理逻辑
     * @param {Object} row 下载文件详细数据
     */
    downloadFile(row) {
      if (this.isExpire(row.updateTime)) {
        return;
      }
      this.$confirm(
        this.$t('filePond.downloadFileTip'),
        this.$t('common.tips'),
        {
          confirmButtonText: this.$t('common.sure'),
          cancelButtonText: this.$t('common.cancel'),
          type: 'warning',
        }
      ).then(() => {
        copyFileUrl({ id: row.id }).then(res => {
          this.$message.success(this.$t('filePond.downFileSuccess'));
          this.downFile('url', res.data, res.headers['content-disposition']);
        });
      });
    },
    /**
     * 批量下载文件
     */
    downloadFiles() {
      this.$confirm(
        this.$t('filePond.downloadFilesTip'),
        this.$t('common.tips'),
        {
          confirmButtonText: this.$t('common.sure'),
          cancelButtonText: this.$t('common.cancel'),
          type: 'warning',
        }
      ).then(() => {
        this.multipleDownload();
      });
    },
    /**
     * 批量下载接口
     */
    multipleDownload() {
      const id = this.selectNoticesIds.toString();
      copyFileUrl({ id }).then(res => {
        this.downFile('url', res.data, res.headers['content-disposition']);
        this.clearMultipleSelect();
      });
    },
    /**
     * 显示上传控件
     * @param {Boolean} type 上传文件类型（单文件[false],多文件[true]）
     */
    uploadFile(type) {
      this.uploadType = type;
      this.dialogVisible = true;
      if (this.uploadType) {
        this.filesId = Date.now();
      } else {
        this.filesId = null;
        this.fileLen = 1;
      }
    },
    /**
     * 关闭上传控件弹窗
     */
    handleClose(done) {
      this.uploadFiles = [];
      done();
    },
    /**
     * 初始化上传控件
     */
    handleFilePondInit() {
      console.log('FilePond has initialized');
    },
    /**
     * 确定上传控件
     */
    sureUploadFile() {
      this.fileLen = this.$refs.pond.getFiles().length;
      let uploadedFileLen = 0;
      this.$refs.pond.$el
        .querySelectorAll('.filepond--action-process-item')
        .forEach(item => {
          item.click();
        });

      this.$refs.pond.$el
        .querySelector('.filepond--root')
        .addEventListener('FilePond:processfile', file => {
          if (file.detail.error === null) {
            uploadedFileLen++;
          }
          if (uploadedFileLen === this.fileLen) {
            this.getList();
            this.dialogVisible = false;
            this.uploadFiles = [];
            uploadedFileLen = 0;
          }
        });
    },
    /**
     * 分页组件-改变每页条数
     */
    handleSizeChange(val) {
      this.search.size = val;
      this.getList();
    },
    /**
     * 分页组件-改变页码
     */
    handleCurrentChange(val) {
      this.search.page = val;
      this.getList();
    },
    /**
     * 分页多选 element ui 组件自带功能
     */
    getRowKeys(row) {
      return row.id;
    },
    /**
     * 文件列表多选操作
     * @param {Arrary} val 已选择条目数据
     */
    handleSelectionChange(val) {
      if (val.length) {
        this.selectNoticesIds = [];
        this.multipleSelection = [];
        this.multipleSelection.push(...val);
        this.multipleSelection.filter(item => {
          return this.selectNoticesIds.push(item.id);
        });
        if (this.multipleSelection.length) {
          this.isDisabled = false;
          this.deleteNums = this.multipleSelection.length;
        } else {
          this.isDisabled = true;
          this.deleteNums = null;
        }
      } else {
        this.isDisabled = true;
        this.deleteNums = null;
        this.selectNoticesIds = [];
        this.multipleSelection = [];
      }
    },
    /**
     * 清空多选操作
     */
    clearMultipleSelect() {
      this.deleteNums = null;
      this.isDisabled = true;
      this.selectNoticesIds = [];
      this.$refs.multipleTable.clearSelection();
    },
    /**
     * 文件下载方法
     * @param {String} type 'url' or 'blob'
     * @param {Any} data url的类型数据
     */
    downFile(type, url, fileName) {
      const a = document.createElement('a');

      let urlData = url;
      if (type === 'blob') {
        const blob = new Blob([urlData]);
        urlData = window.URL.createObjectURL(blob);
        const filelNameArr = fileName.split(';');
        let fileRealName = '';
        filelNameArr.forEach(item => {
          if (item.indexOf('filename=') !== -1) {
            fileRealName = decodeURIComponent(
              item.split('=')[1].replace(/\"/gi, '')
            );
          }
        });

        a.download = fileRealName;
      }
      a.setAttribute('target', '_blank');
      a.href = urlData;
      a.click();
      window.URL.revokeObjectURL(url);
    },

    /**
     * 复制批量下载链接地址
     */
    async copyFileUrlZip() {
      const id = this.selectNoticesIds.toString();
      const res = await copyFileUrl({ id });
      this.zipUrl = res.data;
      this.$nextTick(() => {
        this.$refs.zipUrl.$el.click();
      });
    },
    /**
     * 复制下载链接成功回调处理
     */
    onCopy() {
      this.$message.success(this.$t('filePond.copyFileUrlSuccess'));
    },
    /**
     * 复制批量下载链接地址成功回调处理
     */
    onCopyFiles() {
      this.$message.success(this.$t('filePond.copyFilesUrlSuccess'));
    },
    /**
     * 日期格式化处理
     * @param {Date} date 待处理日期
     */
    formatDate(date) {
      return formatDate(new Date(date));
    },
    /**
     * 储存单位转换
     * @param {Number} data 待处理大小单位
     */
    unitToExpect(data) {
      return unitToExpect(Number(data));
    },
    /**
     * 判断文件是否过期
     * @param {Date} date 过期时间
     * @return {Boolean} true 表示文件已过期
     */
    isExpire(date) {
      if (Date(date) < Date()) {
        this.$confirm(
          this.$t('filePond.fileIsExpire'),
          this.$t('common.tips'),
          {
            confirmButtonText: this.$t('common.sure'),
            cancelButtonText: this.$t('common.cancel'),
            type: 'warning',
          }
        )
          .then(() => {
            this.getList();
          })
          .catch(() => {
            this.getList();
          });
        return true;
      }
    },
    /**
     * 增加上传头部认证
     */
    getToken() {
      return getToken();
    },
    /**
     * 错误消息处理函数
     * @param{JSON} err 错误消息对象
     */
    errorMsg(err) {
      if (err.body && JSON.parse(err.body).desc) {
        return JSON.parse(err.body).desc;
      }
      return this.$t('filePond.labelFileProcessingError');
    },
  },
};
</script>
<style scoped>
/* 上传插件样式优化 -上传按钮 */
.upload-list /deep/ .filepond--action-process-item {
  visibility: hidden;
}
/* 上传插件样式优化 -删除按钮 */
.upload-list /deep/ .filepond--action-revert-item-processing {
  visibility: hidden;
}
/* 上传插件样式优化 -删除按钮 */
.upload-list /deep/ .filepond--action-abort-item-processing {
  visibility: hidden;
}
/* 上传插件样式优化 -状态提示 */
.upload-list /deep/ .filepond--file-status-sub {
  visibility: hidden;
}
/* 上传插件样式优化 -状态文字描述 */
.upload-list /deep/ .filepond--file-status {
  margin: 0;
}
/* 上传插件样式优化 -状态文字描述 */
.upload-list /deep/ .filepond--file-status-main {
  margin-top: 9px;
}
/* 表格样式问题重置 */
.upload-list /deep/ .el-table--border th.gutter:last-of-type {
  display: block !important;
  width: 17px !important;
}
</style>
<style scoped>
.filepond--file-action-button {
  display: none !important;
}
</style>
<style lang="scss" scoped>
.upload-list {
  padding: 20px;
  .tab-content-box {
    padding-left: 10px;
  }
  .operate-btns {
    margin: 20px 0;
    overflow: hidden;
  }
  .pager {
    margin: 20px 0;
    text-align: right;
  }
}
.file-list {
  max-height: 50vh;
  overflow: auto;
}

.navbar {
  height: 50px;
  line-height: 50px;
  overflow: hidden;
  position: relative;
  background: #409eff;
  box-shadow: 0 1px solid #ffffff 4px rgba(0, 21, 41, 0.08);
  .right-menu {
    float: right;
    .code {
      display: inline-block;
      vertical-align: middle;
      margin-right: 20px;
    }
  }
  .avatar-container {
    display: inline-block;
    vertical-align: middle;
    margin-right: 30px;

    .avatar-wrapper {
      margin-top: 5px;
      position: relative;
      color: #ffffff;
      .user-avatar {
        cursor: pointer;
        width: 40px;
        height: 40px;
        border-radius: 10px;
      }

      .el-icon-caret-bottom {
        cursor: pointer;
      }
    }
  }
  .dialog >>> .el-dialog__body {
    padding: 0 20px 30px;
  }
  .el-icon-user {
    margin-left: 5px;
    border: 1px solid #ffffff;
    border-radius: 50%;
    width: 20px;
    height: 20px;
    line-height: 20px;
    text-align: center;
  }
}
</style>
